package com.example.library.service;

import com.example.library.model.Book;
import com.example.library.model.BorrowRecord;
import com.example.library.model.User;
import com.example.library.repository.BookRepository;
import com.example.library.repository.BorrowRecordRepository;
import com.example.library.repository.UserRepository;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;

@Service
@Transactional
public class BorrowService {
    private final BookRepository bookRepository;
    private final UserRepository userRepository;
    private final BorrowRecordRepository borrowRecordRepository;

    public BorrowService(BookRepository bookRepository, UserRepository userRepository, BorrowRecordRepository borrowRecordRepository) {
        this.bookRepository = bookRepository;
        this.userRepository = userRepository;
        this.borrowRecordRepository = borrowRecordRepository;
    }

    @Cacheable(value = "userBorrowHistory", key = "#userId")
    public Page<BorrowRecord> getUserBorrowHistory(Long userId, Pageable pageable) {
        return borrowRecordRepository.findByUserId(userId, pageable);
    }

    @Transactional(isolation = Isolation.SERIALIZABLE)
    public BorrowRecord borrowBook(Long userId, Long bookId) {
        User user = userRepository.getById(userId);
        Book book = bookRepository.findByIdWithPessimisticLock(bookId);

        if(borrowRecordRepository.existsByBookIdAndReturnDateIsNull(bookId)) {
            throw new IllegalStateException("Book is already borrowed");
        }

        BorrowRecord record = new BorrowRecord();
        record.setBook(book);
        record.setUser(user);
        record.setBorrowDate(LocalDate.now());
        return borrowRecordRepository.save(record);
    }
}